// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <type_traits>
#include "logging.h"
#include "zencore.h"

namespace zen {

template<typename T>
class [[nodiscard]] ScopeGuardImpl
{
public:
	inline ScopeGuardImpl(T&& func) : m_guardFunc(func) {}
	~ScopeGuardImpl()
	{
		if (!m_dismissed)
		{
			try
			{
				m_guardFunc();
			}
			catch (const AssertException& Ex)
			{
				ZEN_ERROR("Assert exception in scope guard: {}", Ex.FullDescription());
			}
			catch (const std::exception& Ex)
			{
				ZEN_ERROR("scope guard threw exception: '{}'", Ex.what());
			}
		}
	}

	void Dismiss() { m_dismissed = true; }

private:
	bool m_dismissed = false;
	T	 m_guardFunc;
};

template<typename T>
ScopeGuardImpl<T>
MakeGuard(T&& fn)
{
	return ScopeGuardImpl<T>(std::move(fn));
}

}  // namespace zen
